﻿using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace Xource.Helper
{
    public static partial class XourceHandler
    {
        #region Variables definitions
        public static readonly string _ContentFileName = "Content.xlsx";
        public static readonly string _ContentVirtualPath = "~/Xource";
        static readonly string _ContentKeyRegEx = "^[a-zA-Z][a-zA-Z0-9_]*$";
        static readonly string _WorksheetName = "Content";
        static readonly int _ContentKeyStartRowIndex = 2;
        static readonly int _ContentKeyStartColumnIndex = 1;
        static readonly int _LanguageRowIndex = 1;
        static readonly int _LanguageStartColumnIndex = 2;
        static readonly string _SessionKey = "_XOURCE_LANGUAGE";
        // Dictionary<CONTENT_KEY, Dictionary<Language, CONTENT>> 
        static Dictionary<string, Dictionary<LanguageInfo, string>> textCollection;
        static List<LanguageInfo> languages;
        static LocalizationMode localizationMode;
        static string localFile;
        static bool enableMonitorFlag;
        #endregion

        public static string GetLocalFile()
        {
            if (string.IsNullOrWhiteSpace(localFile))
            {
                localFile = HttpContext.Current.Server.MapPath(string.Format("{0}/{1}", _ContentVirtualPath, _ContentFileName));
            }
            return localFile;
        }

        #region Private methods
        private static void LoadLanguages(ExcelWorksheet worksheet)
        {
            if (worksheet != null)
            {
                try
                {
                    languages = new List<LanguageInfo>();
                    for (int column = _LanguageStartColumnIndex; column <= worksheet.Dimension.End.Column; column++)
                    {
                        string contentKey = string.Empty;
                        if (worksheet.Cells[_LanguageRowIndex, column].Value != null)
                        {
                            languages.Add(new LanguageInfo(
                                  worksheet.Cells[_LanguageRowIndex, column].Value.ToString()
                                , column
                                , column == _LanguageStartColumnIndex));
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            else
            {
                throw new XourceException(string.Format("Invalid worksheet provided"));
            }
        }

        static bool IsValidKey(string input)
        {
            Regex regex = new Regex(_ContentKeyRegEx);
            return regex.IsMatch(input);
        }

        static List<ContentKeyInfo> LoadContentKeys(ExcelWorksheet worksheet)
        {
            List<ContentKeyInfo> result = new List<ContentKeyInfo>();
            if (worksheet != null)
            {
                for (int row = _ContentKeyStartRowIndex; row <= worksheet.Dimension.End.Row; row++)
                {
                    string contentKey = string.Empty;
                    if (worksheet.Cells[row, _LanguageRowIndex].Value != null
                        && IsValidKey(worksheet.Cells[row, _LanguageRowIndex].Value.ToString()))
                    {
                        result.Add(new ContentKeyInfo(
                              row
                            , worksheet.Cells[row, _ContentKeyStartColumnIndex].Value.ToString()));
                    }
                    else
                    {
                        throw new XourceException(string.Format("Content key is invalid in row {0}", row));
                    }
                }
            }
            else
            {
                throw new XourceException(string.Format("Invalid worksheet provided"));
            }
            return result;
        }

        static Stream GetStreamFromFile(string filepath)
        {
            Stream stream = null;

            //// First approach: not good if excel file is open and we want to load it in code
            //stream = new MemoryStream(File.ReadAllBytes(filepath));

            // Second approach: Allows keep excel sheet opened while loading it in code: http://stackoverflow.com/questions/23086227/read-already-opened-file 
            using (FileStream fileStream = File.Open(filepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                try
                {
                    int length = (int)fileStream.Length;  // get file length
                    byte[] buffer = new byte[length];     // create buffer
                    int count;                            // actual number of bytes read
                    int sum = 0;                          // total number of bytes read
                    List<byte> data = new List<byte>();
                    // read until Read method returns 0 (end of the stream has been reached)
                    while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
                    {
                        data.AddRange(buffer);
                        sum += count;  // sum is a buffer offset for next reading
                    }
                    stream = new MemoryStream(data.ToArray());
                }
                finally
                {
                    fileStream.Close();
                }
            }
            return stream;
        }

        static LanguageInfo GetDefaultLanguage()
        {
            return languages.Where(q => q.Default).FirstOrDefault();
        }

        static LanguageInfo GetLanguageByLCID(int LCID)
        {
            return languages.Where(q => q.LCID.Equals(LCID)).FirstOrDefault();
        }
        #endregion
    }
}
